{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 初始化 Pinecone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\27937\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\pinecone\\data\\index.py:1: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from tqdm.autonotebook import tqdm\n"
     ]
    }
   ],
   "source": [
    "from pinecone import Pinecone, ServerlessSpec\n",
    "\n",
    "pinecone = Pinecone(api_key=\"972121d6-7afd-4634-bc4a-3708ce15caaa\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 创建索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "索引 'mnist-index' 不存在，将创建新索引。\n",
      "正在创建新索引 'mnist-index'...\n",
      "索引 'mnist-index' 创建成功。\n",
      "已成功连接到索引 'mnist-index'。\n"
     ]
    }
   ],
   "source": [
    "# 索引名称\n",
    "index_name = \"mnist-index\"\n",
    "\n",
    "# 获取现有索引列表\n",
    "existing_indexes = pinecone.list_indexes()\n",
    "\n",
    "# 检查索引是否存在，如果存在就删除\n",
    "# 这个if是否需要，要看情况而定\n",
    "# 比如有的时候，如果不想要重复删除在创建，这个if就可以不要\n",
    "if any(index['name'] == index_name for index in existing_indexes):\n",
    "    print(f\"索引 '{index_name}' 已存在，正在删除...\")\n",
    "    pinecone.delete_index(index_name)\n",
    "    print(f\"索引 '{index_name}' 已成功删除。\")\n",
    "else:\n",
    "    print(f\"索引 '{index_name}' 不存在，将创建新索引。\")\n",
    "\n",
    "# 创建新索引\n",
    "print(f\"正在创建新索引 '{index_name}'...\")\n",
    "pinecone.create_index(\n",
    "    name=index_name,\n",
    "    dimension=64,  # MNIST 每个图像展平后是一个 64 维向量\n",
    "    metric=\"euclidean\",  # 使用欧氏距离\n",
    "    spec=ServerlessSpec(\n",
    "        cloud=\"aws\",\n",
    "        region=\"us-east-1\"\n",
    "    )\n",
    ")\n",
    "print(f\"索引 '{index_name}' 创建成功。\")\n",
    "\n",
    "# 连接到索引\n",
    "index = pinecone.Index(index_name)\n",
    "print(f\"已成功连接到索引 '{index_name}'。\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 加载 MNIST 数据并插入数据到 Pinecone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从 scikit-learn 库中导入 load_digits 函数\n",
    "# 这个函数用于加载著名的手写数字数据集 MNIST\n",
    "from sklearn.datasets import load_digits\n",
    "\n",
    "# 使用 load_digits 函数加载 MNIST 数据集\n",
    "# n_class=10 表示加载全部 10 个数字类别(0-9)\n",
    "digits = load_digits(n_class=10)\n",
    "\n",
    "# 获取数据集中的特征数据\n",
    "# X 是一个二维数组,每行代表一个样本,每个样本是一个 64 维的向量(8x8 像素展平)\n",
    "X = digits.data\n",
    "\n",
    "# 获取数据集中的标签\n",
    "# y 是一个一维数组,包含每个样本对应的真实数字标签(0-9)\n",
    "y = digits.target\n",
    "\n",
    "# 初始化一个空列表,用于存储转换后的向量数据\n",
    "vectors = []\n",
    "\n",
    "# 遍历所有样本,将数据转换为 Pinecone 可接受的格式\n",
    "for i in range(len(X)):\n",
    "    # 使用样本的索引作为向量的唯一标识符\n",
    "    vector_id = str(i)\n",
    "    \n",
    "    # 将 NumPy 数组转换为 Python 列表\n",
    "    # Pinecone 要求输入数据为 Python 列表格式\n",
    "    vector_values = X[i].tolist()\n",
    "    \n",
    "    # 创建元数据字典,包含该样本的真实标签\n",
    "    # 将标签转换为整数类型,确保数据类型的一致性\n",
    "    metadata = {\"label\": int(y[i])}\n",
    "    \n",
    "    # 将转换后的数据(ID、向量值、元数据)作为元组添加到 vectors 列表中\n",
    "    vectors.append((vector_id, vector_values, metadata))\n",
    "\n",
    "# 定义批处理大小,每批最多包含 1000 个向量\n",
    "# 这是为了避免一次性向 Pinecone 发送过多数据,可能导致请求超时或失败\n",
    "batch_size = 1000\n",
    "\n",
    "# 使用步长为 batch_size 的 range 函数,实现分批处理\n",
    "for i in range(0, len(vectors), batch_size):\n",
    "    # 从 vectors 列表中切片获取一批数据\n",
    "    batch = vectors[i:i + batch_size]\n",
    "    \n",
    "    # 使用 upsert 方法将这批数据上传到 Pinecone 索引中\n",
    "    # upsert 操作会插入新的向量或更新已存在的向量\n",
    "    index.upsert(batch)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 搜索实例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id: 1300, distance: 924.0, label: 3.0\n",
      "id: 1125, distance: 1059.0, label: 3.0\n",
      "id: 1116, distance: 1118.0, label: 3.0\n",
      "id: 385, distance: 1167.0, label: 3.0\n",
      "id: 1478, distance: 1177.0, label: 3.0\n",
      "id: 1290, distance: 1198.0, label: 3.0\n",
      "id: 1180, distance: 1245.0, label: 3.0\n",
      "id: 359, distance: 1251.0, label: 3.0\n",
      "id: 1246, distance: 1261.0, label: 3.0\n",
      "id: 1052, distance: 1276.0, label: 3.0\n",
      "id: 1216, distance: 1303.0, label: 3.0\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGdCAYAAAD9pm++AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAVlElEQVR4nO3caYxV5f3A8d9FBgYYNqlYZRNZg4qA4FZkqaAEUJGigtrMqPGNtTXVJrXSxCWx1FrbRF+0Sa1iTStRUdva0KpVi2LqUlHU0IgUBVxQsDoissnzf2H4henMyGDR4W8/n4SEOefcc597r94v55znTKWUUgIAIqJNaw8AgH2HKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKOwjKpVKgz9t2rSJbt26xQknnBA333xztPaN5/Pnz49KpRJXXXVVg+V1dXVRqVTi0UcfbZVxfVYTJkyISqUSr7766l7Z3yGHHBKVSqXBsldffTUqlUpMmDBhrzxHpVKJQw45ZK/sa3dee+21uOyyy2LcuHHRu3fvqK6ujpqamhg5cmRce+218eGHH36m/S5ZsiSmTp0a+++/f9TU1MTRRx8dv/nNb/by6PlviMI+pra2Nmpra+Occ86JYcOGxZIlS+LCCy+Ms88+u7WH9rlpLjjs3qOPPhqVSiXq6ur26n5feOGF+NnPfhYrVqyIQYMGxemnnx5jx46NVatWxQ9/+MM45phj4t///vce7XPhwoUxfvz4+POf/xzDhw+PKVOmxIoVK6K2tja+973v7dXx89m1be0B0ND8+fMb/Pzggw/G1KlTY8GCBXHOOefE9OnTW2dgzZg3b15cfvnl0bdv39Yeyj6nV69esXz58ujYseNe2d/y5cujqqpqr+xrd4466qh48cUX47DDDmuwvL6+PmbOnBl//etf49prr42f/vSnLdrfu+++G+eff358/PHHsXDhwpg5c2ZERKxbty7Gjh0bN9xwQ0yfPn2vHVXx2TlS2MdNnjw5vvnNb0ZExH333de6g2nCQQcdFEOHDt1rX3xfJlVVVTF06NC9FsyhQ4fGgAED9sq+dueggw5qFISIiC5duuQR3cMPP9zi/d18881RX18fp512WgYhIuLAAw+Mn/zkJxERccMNN/x3g2avEIX/B0aOHBkREWvWrMllO88vb926Na655poYOnRotG/fPmbMmJHbbNq0KebNmxcjR46MmpqaqKmpiWOPPTZuu+22Zp9ryZIlMWnSpOjcuXN069YtTj755HjyySeb3f7Tril8+OGHcd1118Xo0aOjS5cu0alTpxg6dGh861vfipdffjkiPjm3f95550VExNVXX93gusp/HjUtX7486urqok+fPtG+ffs48MADY/bs2fHSSy81ObaPP/44fvrTn8bQoUOjuro6+vTpE5dccknU19c3+3o+zUcffRRz586N/v37R3V1dQwYMCCuvPLK2Lp1a5Pbf9o1hW3btsV1110XQ4YMierq6ujbt29ceumlsXHjxmavd/znNYW6urqYOHFiRETcdtttDd67z/NU3M6jlXbt2rX4MX/6058iImLWrFmN1k2bNi2qq6vjoYceis2bN++dQfKZOX30/8AHH3wQERHt27dvsHzHjh0xY8aMWLx4cYwfPz6GDx8ePXr0iIiIt99+OyZPnhzLli2Lr371qzF+/PgopcQTTzwRdXV18cwzz8RNN93UYH/3339/nH766bF9+/Y4+uij49BDD43nn38+xo0bt8fnrN98882YPHlyvPTSS9G9e/eYMGFCtG/fPv71r3/FL3/5yxg0aFAMHjw4pkyZEtu3b48lS5bEkUceGSNGjMh9DBw4MP9+3333xezZs2PLli0xYsSIOPbYY2PNmjVx5513xh//+MdYtGhRjBs3rsEYzj333FiwYEF07NgxTjrppGjbtm3cdtttsWTJkj0+DbN169Y4+eST47HHHovu3bvHtGnTYsuWLXH99dfH0qVL92giQCklzjrrrLj33nujU6dOcdJJJ0VVVVXceuut8fjjj0fbti3733Ls2LHx1ltvxV/+8pcYMGBAjB07Ntft+j5eddVVcfXVV0dtbW2j0O6pTZs2xbXXXhsRn3yZt9Tzzz8fERGjRo1qtK5du3Zx+OGHxzPPPBMvv/xyDB8+/L8aI/+lwj4hIkpTH8eOHTvKcccdVyKizJ07t9H2AwcOLGvXrm30uKlTp5aIKJdccknZvHlzLn/rrbfK6NGjS0SURYsW5fL6+vpywAEHlIgot9xyS4Pn//73v5/Pd+WVVzZ4ntra2hIR5ZFHHmmw/MQTTywRUc4888zywQcfNFi3atWq8vzzz+fPt956a5P73nX7Tp06lZqamvLggw82WLdo0aJSVVVV+vTpU7Zs2ZLLFyxYUCKi9O3bt6xatSqXr1u3rhx++OH5enZd92l+/OMfl4goI0eOLOvXr8/lK1asKAcffHCTn9+qVatKRJTx48c3WH777beXiCj9+/cva9asyeXr168vI0aMaHZsEVH69evXYNkjjzxSIqLU1tY2O/Yrr7xyt9s059133y21tbWltra2TJ06tfTo0aNERJkxY0bZtGlTi/bx/vvv52t6//33m9xmxowZJSLKH/7whz0eI3uXKOwj/vNLZfv27eXll18udXV1JSJK+/btyyuvvNJo+7vuuqvRvpYuXVoioowZM6Z8/PHHjdY/++yzJSLKqaeemstuueWWEhFl3LhxjbbfunVr6d27d4uj8OSTT5aIKD179iz19fW7fe27i8Ill1xSIqLcdNNNTa7/zne+UyKi3HPPPbls3LhxjQK306JFi/Y4Cn379i0RUR5++OFG637xi1/sURS+9rWvlYgot99+e6N9Pfjgg3s9CjfddFMZMmRIufzyyz/1NTZlzZo1OZ6df84888zy9ttvt3gfr7/+ej5227ZtTW5zzjnnlIgov/3tb/d4jOxdrinsY3aeE27btm0MHjw45s+fH507d4477rij0UXGSqUSp5xySqN9PPDAAxERMWPGjGjTpvFHvPMaw1NPPZXLHnvssYiImD17dqPtq6qqmjwX3JyHHnooIiLmzJkTnTt3bvHjmrPz9ex6gXJXJ5xwQkREvp5t27bF3//+94iIOOussxptP2XKlOjevXuLn3/16tWxevXq6NmzZ57D39WcOXNavK9t27bF008/HZVKpcn3dNKkSbH//vu3eH8tcfHFF8c///nPmDdv3h4/tnfv3lFKiR07dsTq1avj17/+dSxevDiOOOKIePbZZ/fqONk3uKawj6mtrY2IiDZt2kSXLl3iiCOOiJkzZzb5JdazZ89G1xkiIi9Qzp07N+bOndvsc+16Ue+NN96IiIh+/fo1ue2e3DS184L43pops/P19OrV61O3W79+fUREbNiwIbZu3RoHHHBAs7Oi+vXr1+J59rt7b7p27RrdunWL9957b7f72nVs1dXVTW7Tt2/fePfdd1s0ti9KpVKJPn36xPnnnx9HHHFEHHfccXHeeefFc8891+imvf9UU1OTf9+0aVN06dKl0TY7b4bbG/+I4L8jCvuYPbkQ2NyXyo4dOyLikwuRX9QUxs/TztezM5jNOeaYY76I4fzPGzNmTAwZMiSWLVsWq1atikMPPfRTt+/SpUt07do13n///Vi7dm0MGzas0TZr166NiObDyxdHFL6EevfuHRGfnD667LLLWvSYgw46KCI++fUGTWlueVP69OkTERErV65s8WM+Te/evWPlypVxww035OyqT9OjR49o165dvPPOO/HRRx9Fhw4dGm2zevXqFj//7t6b+vr6Fh0l7BxbVVVVrF+/PjZv3txk2Hederyv+spXvhIREe+8885uoxARceSRR8bixYvj2WefbRSFbdu2xYsvvhjV1dUxePDgz2W8tJxrCl9CkydPjoiIe++9t8WP2Xle/s4772y0bvv27bFw4cIW72vSpEkREXHHHXfExo0bd7v9zvnu27dvb3L9nr6eqqqqPGpo6vU88MADe3R6pl+/ftGnT594++23429/+1uj9QsWLGjxvqqqquLoo4+OUkrcc889jdY//PDDsWHDhhbvb3fv3eehvr4+li5dGpVKJfr379+ix+ycvnr33Xc3Wnf//ffH5s2bY9KkSc0e/fIFau0r3XwimpmS+mnb/+dMlF1Nnjy5RES56KKLmpwG+NxzzzWakrpzuuH8+fNz+Y4dO8oVV1yxx1NSJ06cWCKizJkzp2zcuLHBulWrVpVly5blzztn0MyaNavJ17JixYrSoUOH0rVr17Jw4cJG6zdv3lzuuuuuBtM7f/e73+V79Nprr+Xyd955pwwfPnyPZx/96Ec/KhFRjjrqqLJhw4ZcvnLlytKrV6/PNCV1wIABDaYTb9iwoYwaNWqPZh/tfI7Ro0c3O/bPMvvoV7/6VVm5cmWj5WvXri3Tpk0rEVGmT5/eaP3Xv/71MmTIkPLkk082WL5hw4bSpUuXEhENPsN169aVgQMHNvnfEK1DFPYRezsK69atKyNHjiwRUbp161YmTJhQzj777DJt2rTSp0+fvIdhV/fdd1/Zb7/9SkSUY445psyZM6cMGzasVFVVlQsvvHCPorB27doyZMiQEhFl//33L6eeemo544wzyqhRo0qbNm3Kz3/+89z2o48+Kj179swv0PPOO69ccMEFZcmSJQ3G1rFjx7w345RTTimzZ88uJ5xwQunUqVOJiLJ06dIGYzjjjDNKRJROnTqVU089tcycObN069atjBo1qhx77LF7FIUtW7bkVNLu3buXb3zjG2X69OmlQ4cOZfr06TlldVfNRWHHjh3l9NNPLxFRampqymmnnVZmzpxZunfvXkaPHp1je/311xs8rrnPfGfkxowZU+rq6soFF1xQfv/73+f6z3Kfwvjx40tElGHDhpWZM2eWs846qxx//PGlffv2JSLKYYcdVt54441Gj+vXr1+zX/B33313adOmTalUKmXixIll1qxZpVu3biUiyqWXXtrisfH5EoV9xN6OQimffNneeOON5fjjjy9du3Yt7dq1K3369Cnjx48v119/fYN/We+0ePHiMnHixNKpU6fSpUuXcuKJJ5Ynnnii2XsJmotCKZ8cfVxzzTVl+PDhpUOHDqWmpqYMHTq0XHzxxWXFihUNtn366afL5MmTS9euXUulUikRUW699dYG27zyyivloosuKoMGDSrV1dWlc+fOZciQIWX27NnlzjvvbHDzWimlbNu2rVx33XVl8ODBpV27duXggw8uF110UXnvvffyS6+lUSillA8//LD84Ac/KH379i3t2rUrhxxySLniiivKli1b8stwV81FoZRP7v2YN29eGTRoUGnXrl3p1atX+fa3v13q6+vLwIEDS6VSaXRzWHOf+YoVK8qMGTNKjx49Sps2bRp9Tp8lCvfff385//zzy7Bhw0r37t1L27ZtS48ePcr48ePLjTfe2OCGyF19WhRKKeXxxx8vU6ZMKd26dSsdO3Yso0ePbnBkSuurlNLKv6gfSGvXro3+/fvHwIEDY/ny5a09HP4HudAMrWDZsmWxbdu2BsvWrVsXdXV1sX379jj33HNbaWT8r3OkAK1gypQp8dRTT8WIESPiwAMPjDfffDP+8Y9/xMaNG2PMmDGxePFiM3FoFe5TgFZQV1cXpZR44YUX4oknnoj99tsvBg8eHLNmzYrvfve7gkCrcaQAQHJNAYAkCgCkFl9T2N1vQmTvclaPLzvfKV+8lnyvOFIAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQBS29YeAE2rVCqtPQT+nyiltPYQ+BJxpABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgNS2tQfAl08ppbWHAHxGjhQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYDUtrUHwJdPpVJp7SH8TymltPYQ+BJxpABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAUtvWHgBNK6W09hCA/0GOFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgFQppZTWHgQA+wZHCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgCk/wN0PmTwNuXJUQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 导入必要的库\n",
    "import matplotlib.pyplot as plt  # 用于绘图\n",
    "import numpy as np  # 用于数值计算\n",
    "from collections import Counter  # 用于计数\n",
    "\n",
    "# 创建一个手写数字 3 的图像\n",
    "# 使用 numpy 数组表示一个 8x8 的二维图像\n",
    "# 255 表示白色像素,0 表示黑色像素\n",
    "digit_3 = np.array(\n",
    "    [[0, 0, 255, 255, 255, 255, 0, 0],\n",
    "     [0, 0, 0, 0, 0, 255, 0, 0],\n",
    "     [0, 0, 0, 0, 0, 255, 0, 0],\n",
    "     [0, 0, 0, 255, 255, 255, 0, 0],\n",
    "     [0, 0, 0, 0, 0, 255, 0, 0],\n",
    "     [0, 0, 0, 0, 0, 255, 0, 0],\n",
    "     [0, 0, 0, 0, 0, 255, 0, 0],\n",
    "     [0, 0, 255, 255, 255, 255, 0, 0]]\n",
    ")\n",
    "\n",
    "# 将图像像素值从 0-255 的范围缩放到 0-16 的范围\n",
    "# 这是为了匹配 MNIST 数据集中使用的像素值范围\n",
    "digit_3_flatten = (digit_3 / 255.0) * 16\n",
    "\n",
    "# 将二维图像数组展平成一维列表\n",
    "# 这是因为 Pinecone 要求输入向量是一维的\n",
    "query_data = digit_3_flatten.ravel().tolist()\n",
    "\n",
    "# 使用准备好的查询向量在 Pinecone 索引中执行搜索\n",
    "results = index.query(\n",
    "    vector=query_data,\n",
    "    top_k=11,  # 返回距离最近的 11 个结果\n",
    "    include_metadata=True  # 同时返回每个向量的元数据(包括标签)\n",
    ")\n",
    "\n",
    "# 从搜索结果中提取每个匹配项的标签\n",
    "labels = [match['metadata']['label'] for match in results['matches']]\n",
    "\n",
    "# 打印每个匹配结果的详细信息\n",
    "for match, label in zip(results['matches'], labels):\n",
    "    print(f\"id: {match['id']}, distance: {match['score']}, label: {label}\")\n",
    "\n",
    "# 使用投票机制确定最终的分类结果\n",
    "# Counter().most_common(1) 返回出现次数最多的元素\n",
    "# [0][0] 获取该元素的值(即预测的数字)\n",
    "final_prediction = Counter(labels).most_common(1)[0][0]\n",
    "\n",
    "# 使用 matplotlib 显示查询图像和预测结果\n",
    "plt.imshow(digit_3, cmap='gray')  # 显示灰度图像\n",
    "plt.title(f\"Predicted digit: {final_prediction}\", size=15)  # 设置标题,显示预测结果\n",
    "plt.axis('off')  # 关闭坐标轴\n",
    "plt.show()  # 展示图像\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
